using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.ObjectModel;
using Decav.Gatsb.Web;
using System.Text;

public partial class GatsbMap : System.Web.UI.UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Page.ClientScript.RegisterClientScriptInclude("VirtualEarth", "http://dev.virtualearth.net/mapcontrol/v4/mapcontrol.js");
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
            gatsbMap.ClientID, GetScript(), true);
            
    }

    /// <summary>
    /// Gets a collection of the pushpins that are on the map.
    /// </summary>
    public Collection<MapPushpin> Pushpins
    {
        get
        {
            if (ViewState["Pushpins"] == null)
                ViewState["Pushpins"] = new Collection<MapPushpin>();

            return (Collection<MapPushpin>)ViewState["Pushpins"];
        }
    }

    /// <summary>
    /// Gets the name of the function that starts the map.
    /// </summary>
    public string StartFunctionName
    {
        get
        {
            return string.Format("{0}_StartMap", this.ClientID);
        }
    }

    /// <summary>
    /// Gets the name of the variable that is the map instance.
    /// </summary>
    public string MapName
    {
        get
        {
            return string.Format("{0}_map", this.ClientID);
        }
    }

    /// <summary>
    /// Gets the styles applied to the map.
    /// </summary>
    public CssStyleCollection Style
    {
        get
        {
            return gatsbMap.Style;
        }
    }

    /// <summary>
    /// Gets or sets the CSS class of the map.
    /// </summary>
    public string CssClass
    {
        get
        {
            return gatsbMap.Attributes["class"];
        }
        set
        {
            gatsbMap.Attributes["class"] = value;
        }
    }

    /// <summary>
    /// Gets or sets whether the map controls should be shown to allow zooming and panning.
    /// </summary>
    public bool MapControlsVisible
    {
        get
        {
            if (ViewState["MapControlsVisible"] == null)
                return true;

            return (bool)ViewState["MapControlsVisible"];
        }
        set
        {
            ViewState["MapControlsVisible"] = value;
        }
    }

    /// <summary>
    /// Gets or sets whether the distance line should be visible.
    /// </summary>
    public bool DistanceLineVisible
    {
        get
        {
            if (ViewState["DistanceLineVisible"] == null)
                return true;

            return (bool)ViewState["DistanceLineVisible"];
        }
        set
        {
            ViewState["DistanceLineVisible"] = value;
        }
    }

    /// <summary>
    /// Gets or sets the map's center point.
    /// </summary>
    public Decav.Geography.LatLongPoint MapCenter
    {
        get
        {
            if (ViewState["MapCenter"] == null)
                return Decav.Geography.LatLongPoint.Empty;

            return (Decav.Geography.LatLongPoint)ViewState["MapCenter"];
        }
        set
        {
            ViewState["MapCenter"] = value;
        }
    }

    /// <summary>
    /// Gets or sets the zoom level, from 0 to 19.  This will only be set when a <see cref="MapCenter"/> is configured.
    /// </summary>
    public int Zoom
    {
        get
        {
            if (ViewState["Zoom"] == null)
                return 14;

            return (int)ViewState["Zoom"];
        }
        set
        {
            if (value > 19 || value < 1)
                throw new ArgumentOutOfRangeException("value");

            ViewState["Zoom"] = value;
        }
    }

    private string GetScript()
    {
        return _script.Replace("$PUSHPINADD", CreatePushpinJavascript()).Replace("$MAPDIV", gatsbMap.ClientID).Replace("$MAPNAME", this.ClientID);
    }

    public string CreatePushpinJavascript()
    {
        StringBuilder builder = new StringBuilder();
        int i = 0;
        foreach (MapPushpin pushpin in Pushpins)
        {
            builder.AppendFormat(
                _pushpinCtorScript,
                pushpin.Id,
                pushpin.Point.Latitude,
                pushpin.Point.Longitude,
                string.Format("\"Images/Pushpins/{0}.gif\"", Math.Min(i+1, 6)), 
                string.Format("\"{0}\"",pushpin.Name),
                pushpin.DetailHtml == null ? "null" : string.Format("\"{0}\"", pushpin.DetailHtml.Replace(@"""", @"\""")));
            i++;
        }

        if (!MapControlsVisible)
            builder.AppendFormat(_hideControlsScript);

        if (MapCenter != Decav.Geography.LatLongPoint.Empty)
            builder.AppendFormat(_setCenterZoom, MapCenter.Latitude, MapCenter.Longitude, Zoom);


        return builder.ToString().Replace("$MAPNAME", this.ClientID);
    }

    private const string _setCenterZoom = "$MAPNAME_map.SetCenterAndZoom(new VELatLong({0},{1}), {2});\r\n";
    private const string _hideControlsScript = "$MAPNAME_map.HideDashboard();\r\n";

    private const string _pushpinCtorScript = "$MAPNAME_map.AddPushpin(new VEPushpin(\"PP_{0}\", new VELatLong({1},{2}), {3}, {4}, {5}));\r\n";

    private const string _script = @"    var $MAPNAME_map = null;
    
    function $MAPNAME_StartMap()
    {
        $MAPNAME_map = new VEMap(""$MAPDIV"");
        $MAPNAME_map.LoadMap();

        $PUSHPINADD
    }";
}
